package com.csmk.springboot_simple.mybatis;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import com.csmk.springboot_simple.annotation.IgnoreOnDuplicate;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SaveOrUpdateMethod extends AbstractMethod {

    protected SaveOrUpdateMethod(String methodName) {
        super(methodName);
    }

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
        String keyProperty = null;
        String keyColumn = null;

        String sql = generateInsertOrUpdateSql(tableInfo);
        // 使用 MyBatis Plus 的 createSqlSource 方法
        SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, this.methodName, sqlSource, keyGenerator, keyProperty, keyColumn);
    }
    private String generateInsertOrUpdateSql(TableInfo tableInfo) {
        String tableName = tableInfo.getTableName();
        String keyColumn = tableInfo.getKeyColumn();
        // key不包含在 fieldList中 手动添加一下
        List<String> columns =  tableInfo.getFieldList().stream()
                .map(field -> field.getColumn()).collect(Collectors.toList());

        List<String> properties =  tableInfo.getFieldList().stream()
                .map(field -> field.getProperty()).collect(Collectors.toList());

        if(tableInfo.getKeyColumn() != null && tableInfo.getKeyProperty() != null){
            columns.add(0,keyColumn);
            properties.add(0,tableInfo.getKeyProperty());
        }

        String strColumns = String.join(",", columns.stream()
                .toArray(String[]::new));

        String values =properties.stream()
                .map(field -> "#{item." + field + "}") // 恢复为 item.fieldName
                .reduce((a, b) -> a + "," + b)
                .orElse("");

        // 过滤需要忽略的字段
        String updateClause = tableInfo.getFieldList().stream()
                .filter(field -> !isFieldIgnored(field, tableInfo.getEntityType()))
                .map(field -> field.getColumn() + " = VALUES(" + field.getColumn() + ")")
                .reduce((a, b) -> a + "," + b)
                .orElse("");

        return String.format(
                "<script>INSERT INTO %s (%s) VALUES <foreach collection='list' item='item' separator=','> (%s) </foreach> ON DUPLICATE KEY UPDATE %s</script>",
                tableName, strColumns, values, updateClause
        );
    }
    private boolean isFieldIgnored(com.baomidou.mybatisplus.core.metadata.TableFieldInfo field, Class<?> entityType) {
        try {
            // 获取实体类的字段
            Field entityField = entityType.getDeclaredField(field.getProperty());
            // 判断字段是否标记了@IgnoreOnDuplicate注解
            return entityField.isAnnotationPresent(IgnoreOnDuplicate.class);
        } catch (NoSuchFieldException e) {
            // 如果字段不存在，返回false
            return false;
        }
    }
}
